﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AddressablesInfo
{
    public AsyncOperationHandle handle;

    public uint count;

    public AddressablesInfo(AsyncOperationHandle handle)
    {
        this.handle = handle;
    }
}

public class AddressablesMgr : SingletonAutoMono<AddressablesMgr>
{
    private readonly Dictionary<string, AddressablesInfo>
        _assetsDictionary = new Dictionary<string, AddressablesInfo>();

    // 清空Asset
    public void Clear()
    {
        foreach (var item in _assetsDictionary.Values)
        {
            Addressables.Release(item);
        }

        _assetsDictionary.Clear();
        AssetBundle.UnloadAllAssetBundles(true);
        Resources.UnloadUnusedAssets();
        GC.Collect();
    }

    // 卸载单个多标签Asset
    public void ReleaseAsset<T>(Addressables.MergeMode mode, params string[] keys)
    {
        var list = new List<string>(keys);
        var keyName = "";
        foreach (var key in list)
            keyName = key + "_";
        keyName += typeof(T).Name + "_" + mode;

        ReleaseAsset<T>(keyName);
    }

    // 卸载单个单标签Asset
    public void ReleaseAsset<T>(string keyName)
    {
        if (!_assetsDictionary.TryGetValue(keyName, out var value)) return;
        value.count--;
        if (value.count > 0) return;
        Addressables.Release(value);
        _assetsDictionary.Remove(keyName);
    }

    // 加载单个单标签Asset
    public void LoadAssetAsync<T>(string resKey, Action<AsyncOperationHandle<T>> callback)
    {
        var keyName = resKey + "_" + typeof(T).Name;

        if (!_assetsDictionary.TryGetValue(keyName, out var value))
        {
            var handle = Addressables.LoadAssetAsync<T>(resKey);
            var info = new AddressablesInfo(handle);
            _assetsDictionary.TryAdd(keyName, info);
            handle.Completed += _ => { LoadAssetComplete<T>(keyName, handle, callback); };
        }
        else
        {
            var handle = value.handle;
            if (handle.IsDone)
            {
                LoadAssetComplete<T>(keyName, handle.Convert<T>(), callback);
            }
            else
            {
                handle.Completed += _ => { LoadAssetComplete<T>(keyName, handle.Convert<T>(), callback); };
            }
        }
    }

    private void LoadAssetComplete<T>(string keyName, AsyncOperationHandle handle,
        Action<AsyncOperationHandle<T>> callback)
    {
        if (!handle.IsDone) return;
        if (handle.Status == AsyncOperationStatus.Succeeded)
        {
            _assetsDictionary.TryGetValue(keyName, out var value);
            value!.count++;
            callback(handle.Convert<T>());
        }
        else
        {
            if (_assetsDictionary.ContainsKey(keyName))
            {
                _assetsDictionary.Remove(keyName);
            }

            Debug.LogWarning(keyName + " fail to load asset");
        }
    }

    // 加载1-N个多标签Asset, 标记为一个
    public void LoadAssetAsync<T>(Addressables.MergeMode mode,
        Action<T> callback,
        params string[] keys)
    {
        var list = new List<string>(keys);
        var keyName = "";
        foreach (var key in list)
            keyName = key + "_";
        keyName += typeof(T).Name + "_" + mode;
        if (!_assetsDictionary.TryGetValue(keyName, out var value))
        {
            var handle = Addressables.LoadAssetsAsync<T>(list, callback, mode);
            var info = new AddressablesInfo(handle);
            _assetsDictionary.TryAdd(keyName, info);
            handle.Completed += _ => { LoadAssetsComplete<T>(keyName, handle, callback); };
        }
        else
        {
            var handle = value.handle;
            if (handle.IsDone)
            {
                LoadAssetsComplete<T>(keyName, handle.Convert<IList<T>>(), callback);
            }
            else
            {
                handle.Completed += _ => { LoadAssetsComplete<T>(keyName, handle.Convert<IList<T>>(), callback); };
            }
        }
    }

    private void LoadAssetsComplete<T>(string keyName, AsyncOperationHandle<IList<T>> handle,
        Action<T> callback)
    {
        if (!handle.IsDone) return;
        if (handle.Status == AsyncOperationStatus.Succeeded)
        {
            _assetsDictionary.TryGetValue(keyName, out var value);
            value!.count++;
            foreach (var asset in handle.Result)
            {
                callback(asset);
            }
        }
        else
        {
            if (_assetsDictionary.ContainsKey(keyName))
            {
                _assetsDictionary.Remove(keyName);
            }

            Debug.LogWarning(keyName + " fail to load asset");
        }
    }
}